package com.springmvc.context;

import com.springmvc.annotation.AutoWired;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.Service;
import com.springmvc.exception.ContextException;
import com.springmvc.xml.XmlPaser;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebApplicationContext {

    // classpath:springmvc.xml
    String contextConfigLocation;

    List<String> classNameList = new ArrayList<String>();

    // Spring的IOC容器
    public Map<String,Object> iocMap = new ConcurrentHashMap<String,Object>();

    public WebApplicationContext(String contextConfigLocation) {
        this.contextConfigLocation = contextConfigLocation;
    }

    /**
     * 初始化Spring容器
     */
    public void refresh(){
        // 1.解析springmvc.xml DOM4J springmvc.xml
        String basePackage = XmlPaser.getbasePackage(contextConfigLocation.split(":")[1]);
        String[] basePackages = basePackage.split(",");
        if (basePackages.length > 0){
            for (String pack : basePackages) {
                // com.ithong.controller  com.ithong.service ---> /com/ithong/controller
                excuteScanPackage(pack);
            }
        }
        // com.ithong.controller.UserController, com.ithong.service.impl.UserServiceImpl, com.ithong.service.UserService
        System.out.println("扫描之后的内容是："+classNameList);
        // 实例化Spring容器中的bean
        excuteInstance();
        // IOC容器中对象
        System.out.println("SpringIoC容器中对象"+iocMap);
        // 实现Spring容器中对象的注入
        executeAutoWired();

    }

    /**
     * 实现Spring容器中对象依赖注入
     */
    private void executeAutoWired() {
        try {
            if (iocMap.isEmpty()){
                throw new ContextException("没有要初始化的bean对象");
            }
            for (Map.Entry<String, Object> entry : iocMap.entrySet()) {
                String key = entry.getKey();
                Object bean = entry.getValue();
                Field[] fields = bean.getClass().getDeclaredFields();
                for (Field field : fields) {
                    AutoWired autoWiredAnnotation = field.getAnnotation(AutoWired.class);
                    String beanName = autoWiredAnnotation.value();
                    if ("".equals(beanName)){
                        Class<?> type = field.getType();
                        beanName = type.getSimpleName().substring(0,1).toLowerCase() + type.getSimpleName().substring(1);
                    }
                    field.setAccessible(true);
                    // 属性注入 调用反射 给属性赋值
                    field.set(bean,iocMap.get(beanName));
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 实例化Spring容器中bean对象
     */
    private void excuteInstance() {
        if (classNameList.size() == 0){
            // 没有扫描到需要实例化的类
            throw new ContextException("没有要实例化的class");
        }
        try {
            for (String className : classNameList) {
                Class<?> clazz = Class.forName(className);
                if (clazz.isAnnotationPresent(Controller.class)){
                    // 控制层的类 com.ithong.controller.UserController
                    // userController 控制层对象的名字
                    String beanName = clazz.getSimpleName().substring(0,1).toLowerCase() + clazz.getSimpleName().substring(1);
                    iocMap.put(beanName,clazz.newInstance());
                }else if (clazz.isAnnotationPresent(Service.class)){
                    // com.ithong.service.impl.UserServiceImpl
                    Service serviceAnnotation = clazz.getAnnotation(Service.class);
                    String beanName = serviceAnnotation.value();
                    if ("".equals(beanName)){
                        Class<?>[] interfaces = clazz.getInterfaces();
                        for (Class<?> anInterface : interfaces) {
                            String beanName1 = anInterface.getSimpleName().substring(0,1).toLowerCase() + anInterface.getSimpleName().substring(1);
                            iocMap.put(beanName1,clazz.newInstance());
                        }
                    }else {
                        iocMap.put(beanName,clazz.newInstance());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 扫描包
     */
    public void excuteScanPackage(String pack){
        URL url = this.getClass().getClassLoader().getResource("/" + pack.replaceAll("\\.", "/"));
        String path = url.getFile();
        File dir = new File(path);
        for (File f : dir.listFiles()) {
            if (f.isDirectory()){
                // 当前是一个文件目录 com.ithong.service.impl
                excuteScanPackage(pack+"."+f.getName());
            }else {
                // 文件目录
                String className = pack + "." + f.getName().replaceAll(".class","");
                classNameList.add(className);
            }
        }
    }
}
